/**
 ***************************************************************************************************
 *
 * @file app_mp_test.c
 *
 * @brief Functions for mass production test.
 *
 *        [command format]
 *                  ---------------------------------------------------
 *                  | start | cmd_t  |   len   |   data    | checksum |
 *                  ---------------------------------------------------
 *                  | 0xFF  | 1 byte | 2 bytes | len bytes |  1 byte  |
 *                  ---------------------------------------------------
 *        [event format]
 *                  ------------------------------------------------------------
 *                  | start | cmd_t  | status |   len   |   data    | checksum |
 *                  ------------------------------------------------------------
 *                  | 0xEE  | 1 byte | 1 byte | 2 bytes | len bytes |  1 byte  |
 *                  ------------------------------------------------------------
 *
 * Copyright (C) Eker 2021
 *
 ***************************************************************************************************
 */

/*
 * INCLUDE FILES
 ***************************************************************************************************
 */
#include "app.h"


#if (CONFIG_MP_TEST_ENABLE)

#include "h4tl.h"
#include "rw_uart.h"

#include "app_sec.h"
#define APP_LOG_DOMAIN      "mp"
//#define APP_LOG_LEVEL       APP_MP_LOG_LEVEL
//#include "app_log.h"

/*
 * MACROS
 ***************************************************************************************************
 */
#define PIN_MP_TEST_UART_TX             5
#define PIN_MP_TEST_UART_RX             6

#define MP_TEST_UART_BAUDRATE           115200

#define UART_CMD_BUF_LEN                32

#define uart_data_send(buf, len)        do{uart_send_block(HS_UART1, buf, len);}while(0)

#define CMD_START                       0xFF // the start byte of comman packet
#define EVT_START                       0xEE // the start byte of event packet

#define MP_TEST_TIME         			1000

#define MP_COMMON_KEY                   MM_POWER
#define MP_KEY_1                        MM_MENU_UP
#define MP_KEY_2                        MM_MENU_DOWN
#define MP_KEY_3                        MM_MENU_LEFT
#define MP_KEY_4                       	MM_MENU_RIGHT
#define MP_KEY_5                        MM_AC_BACK
#define MP_KEY_6                        MM_MENU
#define MP_KEY_7                        MM_VOLUME_INC
#define MP_KEY_8                        MM_VOLUME_DEC

/*
 * TYPEDEFS
 ***************************************************************************************************
 */
typedef enum 
{
    // software version
    CMD_GET_SW_REV,
    // bt address
    CMD_GET_BT_ADDR,
    CMD_SET_BT_ADDR,
    // advertising
    CMD_START_ADV,
    CMD_STOP_ADV,
    // audio start/stop
    CMD_START_AUDIO,
    CMD_STOP_AUDIO,
    // clear bond info
    CMD_CLEAR_BOND,
    // frequency offset calibration
    CMD_START_FREQ_CALIB,
    // sleep
    CMD_ENTER_SLEEP,
    // reset
    CMD_REBOOT,
    // get power voltage
    CMD_GET_BATT_VOLTAGE,
    // key scan enable/disable
    CMD_ENABLE_KEYSCAN,
    CMD_DISABLE_KEYSCAN,
    // single tune start/stop
    CMD_START_SINGLE_TUNE,
    CMD_STOP_SINGLE_TUNE,
    // get chip uid
    CMD_GET_CHIP_UID,
    // enter HCI mode
    CMD_ENTER_HCI_TEST_MODE,
		//receive frequency offset calibrateion result
		CMD_RECEIVE_FREQ_CALIB_RESULT,
} cmd_t;

/*
 * CONSTANTS
 ***************************************************************************************************
 */
enum
{
    STATUS_SUCCESS,
    STATUS_FAILED,
};

/*
 * LOCAL VARIABLES
 ***************************************************************************************************
 */
static bool mp_test_mode_flag = false;

static co_timer_t cmd_recv_timer;
static uint8_t rx_buf[UART_CMD_BUF_LEN];
static uint8_t rx_idx;
#if (CONFIG_MP_TEST_KEY)
static bool mp_test_keys_pressed;
static co_timer_t mp_test_timer;
static mp_test_mode_t mp_test_mode;

const static struct rwip_eif_api uart_eif = {rw_uart_read, rw_uart_write,
                                             rw_uart_flow_on, rw_uart_flow_off};
static rw_hci_uart_t rw_hci_uart;
static uint8_t       rw_hci_uart_pool[512];
#endif 
/*
 * GLOBAL VARIABLES
 ***************************************************************************************************
 */
#if (CONFIG_MP_TEST_KEY)
T_KEY_HANDLE_GLOBAL_DATA key_handle_global_data;  /* Value to indicate the reconnection key data */
#endif
/*
 * LOCAL FUNCTIONS DECLARATION
 ***************************************************************************************************
 */
static void uart_rx_handler(uint8_t data);

static int char2hex(const char *c, uint8_t *x)
{
    if (*c >= '0' && *c <= '9')
    {
        *x = *c - '0';
    }
    else if (*c >= 'a' && *c <= 'f')
    {
        *x = *c - 'a' + 10;
    }
    else if (*c >= 'A' && *c <= 'F')
    {
        *x = *c - 'A' + 10;
    }
    else
    {
        return -EINVAL;
    }

    return 0;
}

int str_2_bdaddr(const char *str, bd_addr_t *addr)
{
    int i, j;
    uint8_t tmp;

    if (strlen(str) != 17)
    {
        return -EINVAL;
    }

    for (i = 5, j = 1; *str != '\0'; str++, j++)
    {
        if (!(j % 3) && (*str != ':'))
        {
            return -EINVAL;
        }
        else if (*str == ':')
        {
            i--;
            continue;
        }

        addr->addr[i] = addr->addr[i] << 4;

        if (char2hex(str, &tmp) < 0)
        {
            return -EINVAL;
        }

        addr->addr[i] |= tmp;
    }

    return 0;
}

/**
 * @brief Change char into hex
 * eg: 'a' -> 0x0a
 */
uint8_t char_2_hex(const char c)
{
    if (c >= '0' && c <= '9')
    {
        return(c - '0');
    }
    else if (c >= 'a' && c <= 'f')
    {
        return(c - 'a' + 10);
    }
    else if (c >= 'A' && c <= 'F')
    {
        return(c - 'A' + 10);
    }
    return 0;
}

																						 
uint8_t checksum(uint8_t *pdata, uint16_t len)
{
    uint8_t sum = 0;
    for (int i=0; i<len; i++)
    {
        sum += pdata[i];
    }
    return sum;
}

#if (CONFIG_MP_TEST_ENABLE || CONFIG_FREQ_CALIB_ENABLE)
void app_rf_carrier_enable(bool enable, uint32_t freq)
{
    if(enable)
    {
        pmu_lowpower_prevent(PMU_LP_USER);

        pmu_ana_enable(enable, PMU_ANA_RF);

        CPM_ANA_CLK_ENABLE();

        // frequency
        REGW(&HS_DAIF->FREQ_CFG0, MASK_2REG(DAIF_FREQ_REG_ME, 1, DAIF_FREQ_REG_MO, freq));

        // SDM
        REGW(&HS_DAIF->PLL_CTRL1, MASK_2REG(DAIF_DIGI_DIN_BYPASS, 1, DAIF_DIGI_DIN_REG, 0));
        REGW(&HS_DAIF->PLL_CTRL2, MASK_2REG(DAIF_DIN_SDM_TX_ME, 1, DAIF_DATA_SYNC_BYPASS, 1));

        // TX
        REGW(&HS_DAIF->VCO_CTRL0, MASK_3REG(DAIF_TRX_DBG, 1, DAIF_RX_EN_MO, 0, DAIF_TX_EN_MO, 0));
        co_delay_10us(10);
        REGW(&HS_DAIF->VCO_CTRL0, MASK_3REG(DAIF_TRX_DBG, 1, DAIF_RX_EN_MO, 0, DAIF_TX_EN_MO, 1));

        CPM_ANA_CLK_RESTORE();
    }
    else
    {
        CPM_ANA_CLK_ENABLE();

        REGW(&HS_DAIF->FREQ_CFG0, MASK_1REG(DAIF_FREQ_REG_ME, 0));
        REGW(&HS_DAIF->PLL_CTRL1, MASK_2REG(DAIF_DIGI_DIN_BYPASS, 0, DAIF_DIGI_DIN_REG, 0));
        REGW(&HS_DAIF->PLL_CTRL2, MASK_2REG(DAIF_DIN_SDM_TX_ME, 0, DAIF_DATA_SYNC_BYPASS, 0));
        REGW(&HS_DAIF->VCO_CTRL0, MASK_3REG(DAIF_TRX_DBG, 0, DAIF_RX_EN_MO, 0, DAIF_TX_EN_MO, 0));

        CPM_ANA_CLK_RESTORE();

        co_delay_us(100);

        pmu_ana_enable(enable, PMU_ANA_RF);

        pmu_lowpower_allow(PMU_LP_USER);
    }
}
#endif 
																						 
/*
 * LOCAL FUNCTIONS
 ***************************************************************************************************
 */
/**
 ***************************************************************************************************
 * @brief Pack a response packet and send
 *
 * @param[in] cmd: see @ref cmd_t
 * @param[in] status: STATUS_SUCCESS or STATUS_FAILED
 * @param[in] pdata: point to data buffer
 * @param[in] len: length of data
 *
 * @return void
 ***************************************************************************************************
 */
static void uart_cmd_response(cmd_t cmd, uint8_t status, uint8_t *pdata, uint16_t len)
{
    uint8_t buf[100] = {0};
    buf[0] = EVT_START;
    buf[1] = cmd;
    buf[2] = status;
    if (len != 0)
    {
        buf[3] = len & 0xff;
        buf[4] = (len >> 8) & 0xff;
        memcpy(buf+5, pdata, len);
    }
    buf[5+len] = checksum(buf, 5+len);
    uart_data_send(buf, len+6);
}

/**
 ***************************************************************************************************
 * @brief Command parsing and response
 *
 * @param[in] timer: point to cmd receive timer
 * @param[in] param: point to data that transfered by timer
 *
 * @return void
 ***************************************************************************************************
 */
static void cmd_recv_timer_handler(co_timer_t *timer, void *param)
{
//    LOG_INF_ARRAY_EX("uart rx: ", rx_buf, rx_idx);
    if (rx_buf[0] == CMD_START)
    {
        switch(rx_buf[1])
        {
            case CMD_GET_SW_REV://0x00, get app version
            {
							#if (BLE_APP_DIS)
                printf("CMD_GET_SW_REV");
                uint8_t buf[3] = {0};
                uint8_t temp[] = APP_DIS_SW_REV_STR;
                buf[0] = char_2_hex(temp[0]);
                buf[1] = char_2_hex(temp[2]);
                buf[2] = char_2_hex(temp[4]);
                uart_cmd_response(CMD_GET_SW_REV, STATUS_SUCCESS, buf, 3);
								#endif 
            } break;

            case CMD_GET_BT_ADDR://0x01, get MAC address
            {
                printf("CMD_GET_BT_ADDR");
							
							  uint8_t bt_addr11[6]={0X00};
								nvds_tag_len_t l_length=6;
								uint16_t err=nvds_get(NVDS_TAG_BD_ADDRESS, &l_length, bt_addr11); //uint8_t nvds_get(uint8_t tag, nvds_tag_len_t *length, void *buf);
								if (err == 0)
								{
								log_error_array_ex("\nget nvds mac ->", bt_addr11, 6);
								}
								memcpy(&app_env.addr.addr.addr,bt_addr11,6);
                uart_cmd_response(CMD_GET_BT_ADDR, STATUS_SUCCESS, app_env.addr.addr.addr, BD_ADDR_LEN);
            } break;

            case CMD_SET_BT_ADDR://0x02, set MAC address
            {
                printf("CMD_SET_BT_ADDR");
                bd_addr_t loc_addr;
                loc_addr.addr[0] = rx_buf[9];
                loc_addr.addr[1] = rx_buf[8];
                loc_addr.addr[2] = rx_buf[7];
                loc_addr.addr[3] = rx_buf[6];
                loc_addr.addr[4] = rx_buf[5];
                loc_addr.addr[5] = rx_buf[4];
                nvds_put(NVDS_TAG_BD_ADDRESS, BD_ADDR_LEN, loc_addr.addr);
                uart_cmd_response(CMD_SET_BT_ADDR, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_START_ADV://0x03, start ADV
            {
                printf("CMD_START_ADV");
                //app_adv_start();
				//appm_adv_start(1);
							appm_adv_start();
                uart_cmd_response(CMD_START_ADV, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_STOP_ADV://0x04, stop ADV
            {
                printf("CMD_STOP_ADV");
               // app_adv_stop();
//				appm_adv_stop(1,true);
							appm_adv_stop(true);
							
                uart_cmd_response(CMD_STOP_ADV, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_START_AUDIO://0x05, start audio
            {
                printf("CMD_START_AUDIO");
                //app_audio_start();
                uart_cmd_response(CMD_START_AUDIO, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_STOP_AUDIO://0x06, stop audio
            {
                printf("CMD_STOP_AUDIO");
                //app_audio_stop();
                uart_cmd_response(CMD_STOP_AUDIO, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_CLEAR_BOND://0x07, clear bonding information
            {
                printf("CMD_CLEAR_BOND");
               // app_sec_remove_bond();
                uart_cmd_response(CMD_CLEAR_BOND, STATUS_SUCCESS, NULL, 0);
            } break;

        #if CONFIG_FREQ_CALIB_ENABLE
        
            case CMD_START_FREQ_CALIB://0x08, frequency calibration
            {
                printf("CMD_START_FREQ_CALIB");
                app_env.freq_calib_start = 1;

                //response
                uint8_t buf[11] = {0};
                buf[0] = 0x00;//device info type response
                buf[1] = app_env.addr.addr_type;//0x00
								uint8_t bt_addr11[6]={0X00};
								nvds_tag_len_t l_length=6;
								uint16_t err=nvds_get(NVDS_TAG_BD_ADDRESS, &l_length, bt_addr11); //uint8_t nvds_get(uint8_t tag, nvds_tag_len_t *length, void *buf);
								if (err == 0)
								{
								log_error_array_ex("\nget nvds mac ->", bt_addr11, 6);
								}
									
                memcpy(buf+2, bt_addr11, BD_ADDR_LEN);
                buf[8] = app_env.freq_local_handle & 0xff;
                buf[9] = (app_env.freq_local_handle >> 8) & 0xff;
                buf[10] = app_env.xtal32m_ctune;
                uart_cmd_response(CMD_START_FREQ_CALIB, STATUS_SUCCESS, buf, 11);

                //cache the peer device information
                app_env.freq_peer_handle = rx_buf[12]<<8 | rx_buf[11];
                //app_adv_start();
//				appm_adv_start(0);
									appm_adv_start();
            } break;
        #endif

            case CMD_ENTER_SLEEP://0x09, enter deep sleep
            {
                printf("CMD_ENTER_SLEEP");
                uart_cmd_response(CMD_ENTER_SLEEP, STATUS_SUCCESS, NULL, 0);

                //uart test mode trigger pin config
                // pmu_pin_mode_set(BITMASK(PIN_UART_TEST_MODE), PMU_PIN_MODE_PD);
                // gpio_set_direction(BITMASK(PIN_UART_TEST_MODE), GPIO_OUTPUT);
                // gpio_write(BITMASK(PIN_UART_TEST_MODE), GPIO_LOW);

                //enter deep sleep
                sfs_disable();
                rwip_prevent_sleep_clear(RW_PLF_DEEP_SLEEP_DISABLED);
                rwip_sleep();
                co_sleep(POWER_DEEP_SLEEP);
            } break;

            case CMD_REBOOT://0x0A, reboot
            {
                printf("CMD_REBOOT");
                uart_cmd_response(CMD_REBOOT, STATUS_SUCCESS, NULL, 0);
                co_delay_ms(10);
                pmu_force_reboot();
            } break;

            case CMD_GET_BATT_VOLTAGE://0x0B, get battery level
            {
                printf("CMD_GET_BATT_VOLTAGE");
                int16_t vol = adc_battery_voltage_read(NULL);
                uart_cmd_response(CMD_GET_BATT_VOLTAGE, STATUS_SUCCESS, (uint8_t *)&vol, sizeof(int16_t));
            } break;

            case CMD_ENABLE_KEYSCAN://0x0C, enable keyscan
            {
                printf("CMD_ENABLE_KEYSCAN");
                app_env.uart_keyscan = 0x01;
                uart_cmd_response(CMD_ENABLE_KEYSCAN, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_DISABLE_KEYSCAN://0x0D, disable keyscan
            {
                printf("CMD_DISABLE_KEYSCAN");
                app_env.uart_keyscan = 0x00;
                uart_cmd_response(CMD_DISABLE_KEYSCAN, STATUS_SUCCESS, NULL, 0);
            } break;

            case CMD_START_SINGLE_TUNE://0x0E, start single tune
            {
                printf("CMD_START_SINGLE_TONE");
                if (rx_buf[4]<39)//BLE channel is 0-39
                {
                    uart_cmd_response(CMD_START_SINGLE_TUNE, STATUS_SUCCESS, NULL, 0);
                   // app_adv_stop();
					//appm_adv_stop(1,true);
									appm_adv_stop(true);
                    app_rf_carrier_enable(true, 2402+rx_buf[4]*2);
                }
                else
                {
                    uart_cmd_response(CMD_START_SINGLE_TUNE, STATUS_FAILED, NULL, 0);
                }
            } break;

            case CMD_STOP_SINGLE_TUNE://0x0F, stop single tune
            {
                printf("CMD_STOP_SINGLE_TONE");
                if (rx_buf[4]<39)//BLE channel is 0-39
                {
                    uart_cmd_response(CMD_STOP_SINGLE_TUNE, STATUS_SUCCESS, NULL, 0);
                    app_rf_carrier_enable(false, 2402+rx_buf[4]*2);
                }
                else
                {
                    uart_cmd_response(CMD_STOP_SINGLE_TUNE, STATUS_FAILED, NULL, 0);
                }
            } break;

            case CMD_GET_CHIP_UID://0x10, read UID
            {
                printf("CMD_GET_CHIP_UID");
                uint8_t buf[16] = {0};
                sfs_read_uid_ex(buf, 16);
                uart_cmd_response(CMD_GET_CHIP_UID, STATUS_SUCCESS, buf, 16);
//                LOG_INF_ARRAY_EX("Chip UID", buf, 16);
            } break;

            case CMD_ENTER_HCI_TEST_MODE://0x11, enter HCI test mode
            {
                printf("CMD_ENTER_HCI_TEST_MODE");
                uart_cmd_response(CMD_ENTER_HCI_TEST_MODE, STATUS_SUCCESS, NULL, 0);
                mp_test_mode_set(MP_TEST_HCI_MODE);
            } break;
						
            ////////////////////////////////////////////////////////////
            case CMD_RECEIVE_FREQ_CALIB_RESULT: //0x12
            {
                app_env.xtal32m_ctune = rx_buf[4];
                if (nvds_put(NVDS_TAG_XTAL32M_CTUNE, 1, &app_env.xtal32m_ctune) == NVDS_OK)
                {
                    printf("New frequency offset index: %d", app_env.xtal32m_ctune);
                    uint8_t buf[4];
                    buf[0] = 0x01;//frequency calibration result
                    buf[1] = app_env.xtal32m_ctune;
                    buf[2] = rx_buf[5];
                    buf[3] = rx_buf[6];
                    uart_cmd_response(CMD_RECEIVE_FREQ_CALIB_RESULT, STATUS_SUCCESS, buf, sizeof(buf));
                    app_env.freq_calib_start = 0;
                }else
                {//fail
                        //need send result to pc
                    
                }
            } break;
            ////////////////////////////////////////////////////////////

            default:
                break;
        }
    }
    memset(rx_buf, 0, UART_CMD_BUF_LEN);
    rx_idx = 0;
}

/**
 ***************************************************************************************************
 * @brief UART data received handler
 *
 * @param[in] data: byte received
 *
 * @return void
 ***************************************************************************************************
 */
static void uart_rx_handler(uint8_t data)
{
    rx_buf[rx_idx++] = data;

    co_timer_del(&cmd_recv_timer);
    co_timer_set(&cmd_recv_timer, 100, TIMER_ONE_SHOT, cmd_recv_timer_handler, NULL);
}

/*
 * GLOBAL FUNCTIONS
 ***************************************************************************************************
 */
#if (CONFIG_MP_TEST_KEY)
static void mp_test_timer_handler(co_timer_t *timer, void *param)
{
    if (key_handle_global_data.combine_keys_status == PAIRING_COMBINE_KEYS_BIT_MASK)
    {
        printf("%d", mp_test_mode);
        mp_test_mode_set(mp_test_mode);
    }
    else
    {
        printf("mp key is not pressed!!!");
    }
}

void mp_test_mode_check(T_KEY_INDEX_DEF key_index_1, T_KEY_INDEX_DEF key_index_2)
{
	if (mp_test_get_state() || ke_state_get(TASK_APP) == APPM_CONNECTED)
				return;
	
    if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_1) ||
       (key_index_1 == MP_KEY_1 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 1 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_1_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
    else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_2) ||
       (key_index_1 == MP_KEY_2 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 2 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_2_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
	else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_3) ||
       (key_index_1 == MP_KEY_3 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 3 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_3_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
    else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_4) ||
       (key_index_1 == MP_KEY_4 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 4 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_4_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
	else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_5) ||
       (key_index_1 == MP_KEY_5 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 5 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_5_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
    else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_6) ||
       (key_index_1 == MP_KEY_6 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 6 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_6_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
    else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_7) ||
       (key_index_1 == MP_KEY_7 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 7 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_7_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
    else if((key_index_1 == MP_COMMON_KEY && key_index_2 == MP_KEY_8) ||
       (key_index_1 == MP_KEY_8 && key_index_2 == MP_COMMON_KEY))
    {
        printf("MP test mode 8 timer start.");
        mp_test_keys_pressed = true;
        mp_test_mode = MP_TEST_APP_8_MODE;
        key_handle_global_data.combine_keys_status = PAIRING_COMBINE_KEYS_BIT_MASK;
        co_timer_set(&mp_test_timer, MP_TEST_TIME, TIMER_ONE_SHOT, mp_test_timer_handler, NULL);
    }
    else
    {
        if(mp_test_keys_pressed)
        {
            printf("MP test mode timer stop.");
            mp_test_keys_pressed = false;
            co_timer_del(&mp_test_timer);
        }
    }
}
#endif 
/**
 ***************************************************************************************************
 * @brief Set MP test mode
 *
 * @param[in] mode: MP test mode, see @ref mp_test_mode_t
 *
 * @return void
 ***************************************************************************************************
 */
void mp_test_mode_set(mp_test_mode_t mode)
{
    pmu_retention_reg_set(BITMASK(mode));
    pmu_force_reboot();
}

bool mp_test_is_fast_pair_mode(mp_test_mode_t mode)
{
    bool ret = false;

    if (mode == MP_TEST_APP_1_MODE || mode == MP_TEST_APP_2_MODE|| mode == MP_TEST_APP_3_MODE|| mode == MP_TEST_APP_4_MODE ||
        mode == MP_TEST_APP_5_MODE || mode == MP_TEST_APP_6_MODE|| mode == MP_TEST_APP_7_MODE|| mode == MP_TEST_APP_8_MODE)
    {
        ret = true;
    }
    return ret;
}

/**
 ***************************************************************************************************
 * @brief Get MP test mode
 *
 * @param void
 *
 * @return MP test mode, see @ref mp_test_mode_t
 ***************************************************************************************************
 */
mp_test_mode_t mp_test_mode_get(void)
{
    mp_test_mode_t mp_test_mode = MP_TEST_MODE_INVALID;
    uint16_t reg_val = pmu_retention_reg_get();

    switch (reg_val)
    {
        case BITMASK(MP_TEST_APP_1_MODE):
            mp_test_mode = MP_TEST_APP_1_MODE;
            break;

        case BITMASK(MP_TEST_APP_2_MODE):
            mp_test_mode = MP_TEST_APP_2_MODE;
            break;

        case BITMASK(MP_TEST_APP_3_MODE):
            mp_test_mode = MP_TEST_APP_3_MODE;
            break;

        case BITMASK(MP_TEST_APP_4_MODE):
            mp_test_mode = MP_TEST_APP_4_MODE;
            break;

        case BITMASK(MP_TEST_APP_5_MODE):
            mp_test_mode = MP_TEST_APP_5_MODE;
            break;

        case BITMASK(MP_TEST_APP_6_MODE):
            mp_test_mode = MP_TEST_APP_6_MODE;
            break;

        case BITMASK(MP_TEST_APP_7_MODE):
            mp_test_mode = MP_TEST_APP_7_MODE;
            break;

        case BITMASK(MP_TEST_APP_8_MODE):
            mp_test_mode = MP_TEST_APP_8_MODE;
            break;

        case BITMASK(MP_TEST_UART_MODE):
            mp_test_mode = MP_TEST_UART_MODE;
            break;

        case BITMASK(MP_TEST_HCI_MODE):
            mp_test_mode = MP_TEST_HCI_MODE;
            break;

        default:
            break;
    }

    return mp_test_mode;
}

/**
 ***************************************************************************************************
 * @brief MP App test mode check
 *
 * @param void
 *
 * @return void
 ***************************************************************************************************
 */
#if (CONFIG_MP_TEST_KEY)
void mp_test_app_mode_check(void)
{
    mp_test_mode_t mode = mp_test_mode_get();

    if (mode == MP_TEST_MODE_INVALID)
        return;

    mp_test_mode_flag = true;

    uint8_t addr[] = MP_TEST_BASE_ADDR;
    bd_addr_t bd_addr;
    str_2_bdaddr((const char*)addr, &bd_addr);

    switch (mode)
    {
        case MP_TEST_APP_1_MODE:
            printf("MP_TEST_APP_1_MODE");
            bd_addr.addr[0] += 1;
            break;

        case MP_TEST_APP_2_MODE:
            printf("MP_TEST_APP_2_MODE");
            bd_addr.addr[0] += 2;
            break;

        case MP_TEST_APP_3_MODE:
            printf("MP_TEST_APP_3_MODE");
            bd_addr.addr[0] += 3;
            break;

        case MP_TEST_APP_4_MODE:
            printf("MP_TEST_APP_4_MODE");
            bd_addr.addr[0] += 4;
            break;

        case MP_TEST_APP_5_MODE:
            printf("MP_TEST_APP_5_MODE");
            bd_addr.addr[0] += 5;
            break;

        case MP_TEST_APP_6_MODE:
            printf("MP_TEST_APP_6_MODE");
            bd_addr.addr[0] += 6;
            break;

        case MP_TEST_APP_7_MODE:
            printf("MP_TEST_APP_7_MODE");
            bd_addr.addr[0] += 7;
            break;

        case MP_TEST_APP_8_MODE:
            printf("MP_TEST_APP_8_MODE");
            bd_addr.addr[0] += 8;
            break;

        default:
            break;
    }

//    LOG_INF_ARRAY_EX("bd_addr", bd_addr.addr, BD_ADDR_LEN);
    gapm_set_bdaddr(&bd_addr);
    memcpy(app_env.addr.addr.addr, bd_addr.addr, BD_ADDR_LEN);
}
#endif 
/**
 ***************************************************************************************************
 * @brief MP UART test mode check
 *
 * @param void
 *
 * @return void
 ***************************************************************************************************
 */
void mp_test_uart_mode_check(void)
{
    if (mp_test_mode_get() == MP_TEST_UART_MODE)
    {
//				app_sec_remove_bond();
        printf("MP_TEST_UART_MODE");
        mp_test_mode_flag = true;

        pinmux_config(PIN_MP_TEST_UART_TX,  PINMUX_UART1_SDA_O_CFG);
        pinmux_config(PIN_MP_TEST_UART_RX,  PINMUX_UART1_SDA_I_CFG);
        pmu_pin_mode_set(BITMASK(PIN_MP_TEST_UART_TX), PMU_PIN_MODE_PP);
        pmu_pin_mode_set(BITMASK(PIN_MP_TEST_UART_RX), PMU_PIN_MODE_PU);

        uart_open(HS_UART1, MP_TEST_UART_BAUDRATE, UART_FLOW_CTRL_DISABLED, uart_rx_handler);
    }
}

/**
 ***************************************************************************************************
 * @brief MP HCI test mode check
 *
 * @param void
 *
 * @return void
 ***************************************************************************************************
 */
#if (CONFIG_MP_TEST_KEY)
void mp_test_hci_mode_check(void)
{
    if (mp_test_mode_get() == MP_TEST_HCI_MODE)
    {
        wdt_enable(0);
    #if CONFIG_INTERNAL_DCDC_ENABLE
        pmu_dcdc_enable(true);
    #else
        pmu_dcdc_enable(false);
    #endif
    #if CONFIG_INTERNAL_32K_ENABLE
        pmu_select_32k(PMU_32K_SEL_RC);
    #else
        pmu_select_32k(PMU_32K_SEL_32768HZ_XTAL);
    #endif
        pmu_xtal32m_change_param(XTAL32M_CTUNE_DEFAULT);
        co_power_sleep_enable(false);
        sc.rw_sleep_enable = false;

        gpio_open();

    #if (CONFIG_LOG_OUTPUT_ENABLE)
        pinmux_config(4,  PINMUX_UART0_SDA_O_CFG);
        uart_open(HS_UART0, UART_BAUDRATE_LOG_OUPUT, UART_FLOW_CTRL_DISABLED, NULL);
        printf("****************************************");
        printf("* BLE APP RC                           *");
        printf("* Version: V%s                      *", APP_DIS_SW_REV_STR);
        printf("* Compile at %s %s      *", __TIME__, __DATE__);
        printf("****************************************");
        printf("HCI mode starting...");
    #endif

        pinmux_config(5,  PINMUX_UART1_SDA_O_CFG);
        pinmux_config(6,  PINMUX_UART1_SDA_I_CFG);
        pmu_pin_mode_set(BITMASK(5), PMU_PIN_MODE_PP);
        pmu_pin_mode_set(BITMASK(6), PMU_PIN_MODE_PU);

        rw_uart_open(UART_BAUDRATE_HCI, &rw_hci_uart, rw_hci_uart_pool, sizeof(rw_hci_uart_pool));

        rwip_init(RESET_NO_ERROR);

    #if CONFIG_RF_TX_POWER_SET_ENABLE
        rf_tx_power_set(false, RF_TX_POWER);
    #endif

        h4tl_init(0, &uart_eif);
        rwip_reset();

        while(1)
        {
            rwip_schedule();
        }
    }
}
#endif 
/**
 ***************************************************************************************************
 * @brief Is MP test mode or not?
 *
 * @param void
 *
 * @return true: is mp test mode, false: isn't mp test mode
 ***************************************************************************************************
 */
bool mp_test_get_state(void)
{
    return mp_test_mode_flag;
}

/**
 ***************************************************************************************************
 * @brief Report the value of keyscan
 *
 * @param[in] key_val: value of a key
 *
 * @return void
 ***************************************************************************************************
 */
void mp_test_report_keyscan_data(uint16_t key_val)
{
    uint8_t buf[] = {key_val&0xff, (key_val>>8)&0xff};
    uart_cmd_response(CMD_ENABLE_KEYSCAN, STATUS_SUCCESS, buf, sizeof(buf));
}

#if (CONFIG_FREQ_CALIB_ENABLE)
/**
 ***************************************************************************************************
 * @brief Report the result of frequency calibration
 *
 * @param void
 *
 * @return void
 ***************************************************************************************************
 */
void mp_test_report_freq_calib_result(void)
{
    uint8_t buf[2];
    buf[0] = 0x01;//frequency calibration result
    buf[1] = app_env.xtal32m_ctune;
    uart_cmd_response(CMD_START_FREQ_CALIB, STATUS_SUCCESS, buf, sizeof(buf));
    app_env.freq_calib_start = 0;
}
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
co_timer_t power_on_flag_timer;
void mp_test_enter_single_tone_mode_set(void)
{
		co_timer_del(&power_on_flag_timer);
		app_env.single_tone_test_enable = true;
		printf("Enter single tone mode...\n");
	
#if CONFIG_LED_ENABLE
		led_1_on();
#endif

		app_rf_carrier_enable(true, 2442);
		rf_tx_power_set(false, 0);
}

static void power_on_flag_timer_handler(co_timer_t *timer, void *param)
{
		app_env.power_on_flag = false;
		co_timer_del(&power_on_flag_timer);
}

void power_on_flag_check(void)
{
		app_env.power_on_flag = true;
		co_timer_set(&power_on_flag_timer, 200, TIMER_ONE_SHOT, power_on_flag_timer_handler, NULL);
}

#endif /* CONFIG_MP_TEST_ENABLE */
